package com.innovation.ic.sc.base.service.sc.impl;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.innovation.ic.sc.base.mapper.sc.UserManagementMapper;
import com.innovation.ic.sc.base.model.sc.User;
import com.innovation.ic.sc.base.model.sc.UserManagement;
import com.innovation.ic.sc.base.pojo.constant.handler.RedisStorage;
import com.innovation.ic.sc.base.pojo.enums.RedisKeyPrefixEnum;
import com.innovation.ic.sc.base.pojo.variable.ServiceResult;
import com.innovation.ic.sc.base.pojo.variable.UserManagementPojo;
import com.innovation.ic.sc.base.pojo.variable.UserManagementRedisPojo;
import com.innovation.ic.sc.base.service.ServiceHelper;
import com.innovation.ic.sc.base.service.sc.UserManagementService;
import com.innovation.ic.sc.base.vo.UserManagementVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * DepartmentService的具体实现类
 */
@Service
@Transactional
public class UserManagementServiceImpl extends ServiceImpl<UserManagementMapper, UserManagement> implements UserManagementService {
    private static final Logger log = LoggerFactory.getLogger(UserManagementServiceImpl.class);

    @Resource
    private ServiceHelper serviceHelper;

    /**
     * 进行批量添加人员数据
     *
     * @return
     */
    @Override
    public ServiceResult<Boolean> addUserManagement(UserManagementVo userManagementVo) {
        ServiceResult<Boolean> serviceResult = new ServiceResult<>();
        //先清除redis中缓存
        User user = serviceHelper.getUserMapper().selectById(userManagementVo.getUserId());
        List<String> redisList = this.deleteRedisUserManagement(user, userManagementVo.getDepartmentId());//批量删除redis中的所有数据
        serviceHelper.getRedisManager().del(redisList);//进行删除

        //清空历史数据保证数据一致（用户与部门进行条件删除）
        QueryWrapper<UserManagement> userManagementQueryWrapper = new QueryWrapper<>();
        userManagementQueryWrapper.eq("user_id", userManagementVo.getUserId());
        userManagementQueryWrapper.eq("department_id", userManagementVo.getDepartmentId());
        baseMapper.delete(userManagementQueryWrapper);

        ArrayList<UserManagement> userManagements = new ArrayList<>();//人员管理集合
        List<String> managedUserId = userManagementVo.getManagedUserId();//被管理用户id
        for (String managedUserIdData : managedUserId) {
            UserManagement userManagement = new UserManagement();
            userManagement.setDepartmentId(userManagementVo.getDepartmentId());//部门id
            userManagement.setManagedUserId(managedUserIdData);//被管理用户id
            userManagement.setUserId(userManagementVo.getUserId());//用户id
            userManagement.setCreateTime(new Date());//时间
            userManagements.add(userManagement);
        }
        //进行批量添加人员管理
        baseMapper.insertBatchSomeColumn(userManagements);
        serviceResult.setMessage(ServiceResult.INSERT_SUCCESS);
        serviceResult.setSuccess(Boolean.TRUE);
        return serviceResult;
    }

    /**
     * 查询当前部门下此用户人员数据数据
     *
     * @return
     */
    @Override
    public ServiceResult<List<UserManagementPojo>> findDepartmentUser(UserManagementVo userManagementVo) {
        ServiceResult<List<UserManagementPojo>> serviceResult = new ServiceResult<>();
        List<UserManagementPojo> userManagementPojoList = new ArrayList<>();//存放封装后的参数
        if (userManagementVo.getDepartmentId() == null) {//部门id为空 直接用用户id 去redis中查询
            String key = RedisKeyPrefixEnum.USER_MANAGEMENT_DATA.getCode() + "_" + userManagementVo.getUserId();
            Object redisUserManagement = serviceHelper.getRedisManager().get(key);//通过userid从redis中获取对应数据
            if (redisUserManagement == null) {//因缓存中不存在要去 mysql中查询
                User user = serviceHelper.getUserMapper().selectById(userManagementVo.getUserId());
                if (user == null) {//因不存在直接存入缓存 避免二次查询数据库
                    String redisKey = RedisKeyPrefixEnum.USER_MANAGEMENT_DATA.getCode() + "_" + userManagementVo.getUserId();
                    serviceHelper.getRedisManager().set(redisKey, RedisStorage.EMPTY_VALUE);
                    serviceResult.setMessage(ServiceResult.SELECT_SUCCESS);
                    serviceResult.setSuccess(Boolean.TRUE);
                    return serviceResult;
                }
                List<UserManagementRedisPojo> userManagementRedisPojoList = this.selectUserData(user, false);//主账号子账号相关数据
                for (UserManagementRedisPojo userManagementRedisPojo : userManagementRedisPojoList) {
                    String redisKey = RedisKeyPrefixEnum.USER_MANAGEMENT_DATA.getCode() + "_" + userManagementRedisPojo.getUserId();
                    String apiResultJson = JSONObject.toJSONString(userManagementRedisPojoList, SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue);
                    serviceHelper.getRedisManager().set(redisKey, apiResultJson);
                }
                for (UserManagementRedisPojo userManagementRedisPojo : userManagementRedisPojoList) {//因为和前端已经联调好了 不方便动返回参数只能封装
                    UserManagementPojo userManagementPojo = this.packageUserManagementPojo(userManagementRedisPojo);
                    userManagementPojoList.add(userManagementPojo);
                }
                serviceResult.setMessage(ServiceResult.SELECT_SUCCESS);
                serviceResult.setSuccess(Boolean.TRUE);
                serviceResult.setResult(userManagementPojoList);
                return serviceResult;
            }
            if (redisUserManagement.equals(RedisStorage.EMPTY_VALUE)) {//为空字符串或根本不存在redis中数据
                serviceResult.setMessage(ServiceResult.SELECT_SUCCESS);
                serviceResult.setSuccess(Boolean.TRUE);
                return serviceResult;
            }
            //redis 中有值正常流程
            List<UserManagementRedisPojo> redisAll = JSONObject.parseArray((String) redisUserManagement, UserManagementRedisPojo.class);//反序列化数据
            for (UserManagementRedisPojo userManagementRedisPojo : redisAll) {
                UserManagementPojo userManagementPojo = this.packageUserManagementPojo(userManagementRedisPojo);//因为和前端已经联调好了 不方便动返回参数只能封装
                userManagementPojoList.add(userManagementPojo);
            }
            serviceResult.setMessage(ServiceResult.SELECT_SUCCESS);
            serviceResult.setSuccess(Boolean.TRUE);
            serviceResult.setResult(userManagementPojoList);
            return serviceResult;
        } else {//传递参数 既带部门id 也带用户id
            String key = RedisKeyPrefixEnum.USER_MANAGEMENT_DATA.getCode() + "_" + userManagementVo.getUserId() + "_" + userManagementVo.getDepartmentId();
            Object redisUserManagement = serviceHelper.getRedisManager().get(key);//通过userid从redis中获取对应数据
            if (redisUserManagement == null) {//因缓存中不存在要去 mysql中查询
                Map<String, UserManagementRedisPojo> usersMap = new HashMap<>();//存放用户id 与账号 用于筛选条件
                User user = serviceHelper.getUserMapper().selectById(userManagementVo.getUserId());
                List<UserManagementRedisPojo> userList = this.selectUserData(user, true);//获取当前用户主账号与子账号相关数据
                for (UserManagementRedisPojo userManagementRedisPojo : userList) {
                    usersMap.put(userManagementRedisPojo.getUserId(), userManagementRedisPojo);
                }
                List<String> userIdList = this.selectUser(user);//获取当前用户主账号与子账号所有id
                QueryWrapper<UserManagement> userManagementQueryWrapper = new QueryWrapper<>();
                userManagementQueryWrapper.eq("department_id", userManagementVo.getDepartmentId());
                userManagementQueryWrapper.in("user_id", userIdList);
                List<UserManagement> list = baseMapper.selectList(userManagementQueryWrapper);
                if (list.size() == 0) {//因不存在直接存入缓存 避免二次查询数据库
                    for (String data : userIdList) {
                        String redisKey = RedisKeyPrefixEnum.USER_MANAGEMENT_DATA.getCode() + "_" + data + "_" + userManagementVo.getDepartmentId();
                        serviceHelper.getRedisManager().set(redisKey, RedisStorage.EMPTY_VALUE);
                    }
                    serviceResult.setMessage(ServiceResult.SELECT_SUCCESS);
                    serviceResult.setSuccess(Boolean.TRUE);
                    return serviceResult;
                }
                List<UserManagementRedisPojo> userManagementRedisPojoArrayList = new ArrayList<>();
                //数据库中有值 把值存入缓存中
                for (UserManagement userManagement : list) {//因为和前端已经联调好了 不方便动返回参数只能封装
                    for (String userId : userIdList) {
                        if (userId.equals(userManagement.getManagedUserId())) {
                            UserManagementRedisPojo userManagementRedisPojo = usersMap.get(userManagement.getManagedUserId());
                            userManagementRedisPojoArrayList.add(userManagementRedisPojo);
                            UserManagementPojo userManagementPojo = this.packageUserManagementPojo(userManagementRedisPojo);
                            userManagementPojoList.add(userManagementPojo);
                        }
                    }
                }

                for (String userId : userIdList) {//把属于一个主账号下的所有子账号重新添加缓存
                    String redisKey = RedisKeyPrefixEnum.USER_MANAGEMENT_DATA.getCode() + "_" + userId + "_" + userManagementVo.getDepartmentId();
                    String apiResultJson = JSONObject.toJSONString(userManagementRedisPojoArrayList, SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue);
                    serviceHelper.getRedisManager().set(redisKey, apiResultJson);
                }

                serviceResult.setMessage(ServiceResult.SELECT_SUCCESS);
                serviceResult.setSuccess(Boolean.TRUE);
                serviceResult.setResult(userManagementPojoList);
                return serviceResult;
            }
            if (redisUserManagement.equals(RedisStorage.EMPTY_VALUE)) {//为空字符串或根本不存在redis中数据
                serviceResult.setMessage(ServiceResult.SELECT_SUCCESS);
                serviceResult.setSuccess(Boolean.TRUE);
                return serviceResult;
            }
            List<UserManagementRedisPojo> redisAll = JSONObject.parseArray((String) redisUserManagement, UserManagementRedisPojo.class);//反序列化数据
            for (UserManagementRedisPojo userManagementRedisPojo : redisAll) {
                UserManagementPojo userManagementPojo = this.packageUserManagementPojo(userManagementRedisPojo);//因为和前端已经联调好了 不方便动返回参数只能封装
                userManagementPojoList.add(userManagementPojo);
            }
            serviceResult.setMessage(ServiceResult.SELECT_SUCCESS);
            serviceResult.setSuccess(Boolean.TRUE);
            serviceResult.setResult(userManagementPojoList);
            return serviceResult;
        }

    }

    /**
     * 删除人员管理数据
     *
     * @return
     */
    @Override
    public ServiceResult<Boolean> dellUserManagement(UserManagementVo userManagementVo) {
        ServiceResult<Boolean> serviceResult = new ServiceResult<>();
        QueryWrapper<UserManagement> userManagementQueryWrapper = new QueryWrapper<>();
        userManagementQueryWrapper.eq("id", userManagementVo.getId());
        baseMapper.delete(userManagementQueryWrapper);
        serviceResult.setMessage(ServiceResult.DELETE_SUCCESS);
        serviceResult.setSuccess(Boolean.TRUE);
        return serviceResult;
    }

    /**
     * 将user_management表的数据导入到redis
     *
     * @return
     */

    public void initUserManagementData() {
        Map<String, UserManagementRedisPojo> usersMap = new HashMap<>();//存放用户id 与账号 用于筛选条件
        Map<String, List<UserManagementRedisPojo>> userMap = new HashMap<>();//存放第一种情况 redis存储结果集
        Map<Integer, Integer> departmentIdMap = new HashMap<>();//用于存放部门id 当做条件
        // 删除redis中的人员管理相关数据
        Boolean deleteResult = serviceHelper.getRedisManager().delRedisDataByKeyPrefix(RedisKeyPrefixEnum.USER_MANAGEMENT_DATA.getCode() + "*");
        if (deleteResult) {
            log.info("删除[{}]开头的数据成功", RedisKeyPrefixEnum.USER_MANAGEMENT_DATA.getCode());
        }
        List<User> userList = serviceHelper.getUserMapper().selectList(null);//获取到用户表所有数据
        List<UserManagement> userManagementList = serviceHelper.getUserManagementMapper().selectList(null);//获取到所有人员管理数据
        for (UserManagement userManagement : userManagementList) {//获取当前部门表中 所有部门
            if (departmentIdMap.containsKey(userManagement.getDepartmentId())) {//如果有重复部门id直接跳过
                continue;
            }
            departmentIdMap.put(userManagement.getDepartmentId(), userManagement.getDepartmentId());
        }
        for (User user : userList) {//遍历user表数据 以用户id为key 并对value进行封装数据
            List<UserManagementRedisPojo> usersList = this.selectUserData(user, false);//获取主账号与子账号相关数据(id与名称)
            userMap.put(user.getId(), usersList);
            UserManagementRedisPojo userManagementRedisPojo = this.packageUser(user);
            usersMap.put(user.getId(), userManagementRedisPojo);
        }
        //第一种情况开始redis同步
        userMap.forEach((key, value) -> {
            if (value.size() == 0) {
                String redisKey = RedisKeyPrefixEnum.USER_MANAGEMENT_DATA.getCode() + "_" + key;
                serviceHelper.getRedisManager().set(redisKey, RedisStorage.EMPTY_VALUE);
            }else {
                String redisKey = RedisKeyPrefixEnum.USER_MANAGEMENT_DATA.getCode() + "_" + key;
                String apiResultJson = JSONObject.toJSONString(value, SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue);
                serviceHelper.getRedisManager().set(redisKey, apiResultJson);
            }
        });
        //第二种情况开始redis同步
        for (User user : userList) {//遍历所有用户
            List<String> userIdList = this.selectUser(user);//获取主账号id(包含子账号id)
            QueryWrapper<UserManagement> userManagementQueryWrapper = new QueryWrapper<>();
            userManagementQueryWrapper.in("user_id", userIdList);
            List<UserManagement> userManagementListData = baseMapper.selectList(userManagementQueryWrapper);//获取到人员管理相关联数据
            if (userManagementListData.size() == 0) {
                for (String userIdData : userIdList) {//没有人员管理数据 那就把当前用户id 管理所有部门id 并存入redis 一个空字符串
                    departmentIdMap.forEach((key, value) -> {
                        String redisKey = RedisKeyPrefixEnum.USER_MANAGEMENT_DATA.getCode() + "_" + userIdData + "_" + key;
                        serviceHelper.getRedisManager().set(redisKey, RedisStorage.EMPTY_VALUE);
                    });
                }
            } else {
                for (UserManagement userManagementData : userManagementListData) {
                    ArrayList<UserManagementRedisPojo> redisUserManagement = new ArrayList<>();
                    QueryWrapper<UserManagement> userManagementsQueryWrapper = new QueryWrapper<>();
                    userManagementsQueryWrapper.in("user_id", userIdList);
                    userManagementsQueryWrapper.eq("department_id", userManagementData.getDepartmentId());
                    List<UserManagement> userManagementDataList = baseMapper.selectList(userManagementsQueryWrapper);
                    for (UserManagement userManagement : userManagementDataList) {
                        UserManagementRedisPojo userManagementRedisPojo = usersMap.get(userManagement.getManagedUserId());
                        redisUserManagement.add(userManagementRedisPojo);
                    }
                    String redisKey = RedisKeyPrefixEnum.USER_MANAGEMENT_DATA.getCode() + "_" + user.getId() + "_" + userManagementData.getDepartmentId();
                    String apiResultJson = JSONObject.toJSONString(redisUserManagement, SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue);
                    serviceHelper.getRedisManager().set(redisKey, apiResultJson);
                }
            }
        }
    }

    private List<String> selectUser(User user) {//获取当前主账号id与所有的子账号id
        List<String> list = new ArrayList<>();
        if (user.getFatherId() == null) {//判断当前用户是主
            QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
            userQueryWrapper.eq("father_id", user.getId());//需要查询主账号下的所有子账号id
            List<User> users = serviceHelper.getUserMapper().selectList(userQueryWrapper);//所有子账号id
            for (User user1 : users) {
                String id = user1.getId();
                list.add(id);//子账号id存入
            }
            list.add(user.getId());//主账号id存入
        } else {//判断当前用户是子
            User userMain = serviceHelper.getUserMapper().selectById(user.getFatherId());//获取主账号
            QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
            userQueryWrapper.eq("father_id", userMain.getId());//获取主账号下的所有子账号
            List<User> users = serviceHelper.getUserMapper().selectList(userQueryWrapper);//所有子账号id
            for (User user1 : users) {
                String id = user1.getId();
                list.add(id);//子账号id存入
            }
            list.add(userMain.getId());//主账号id存入
        }
        return list;
    }

    private List<UserManagementRedisPojo> selectUserData(User user, Boolean departmentData) {//获取当前主账号数据(子账号数据)
        List<UserManagementRedisPojo> list = new ArrayList<>();
        if (user.getFatherId() == null) {//判断当前用户是主
            QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
            userQueryWrapper.eq("father_id", user.getId());//需要查询主账号下的所有子账号id
            List<User> users = serviceHelper.getUserMapper().selectList(userQueryWrapper);//所有子账号id
            for (User user1 : users) {
                list.add(this.packageUser(user1));//子账号存入
            }
            if (departmentData == true) {
                list.add(this.packageUser(user));//主账号存入
            }

        } else {//判断当前用户是子
            User userMain = serviceHelper.getUserMapper().selectById(user.getFatherId());//获取主账号
            QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
            userQueryWrapper.eq("father_id", userMain.getId());//获取主账号下的所有子账号
            List<User> users = serviceHelper.getUserMapper().selectList(userQueryWrapper);//所有子账号id
            for (User user1 : users) {
                list.add(this.packageUser(user1));//子账号存入
            }
            if (departmentData == true) {
                list.add(this.packageUser(userMain));//主账号存入
            }
        }
        return list;
    }

    private UserManagementPojo packageUserManagementPojo(UserManagement userManagement) {//封装对象 返回前端
        //通过userId获取对应的用户信息
        User user = serviceHelper.getUserMapper().selectById(userManagement.getUserId());
        UserManagementPojo userManagementPojo = new UserManagementPojo();
        userManagementPojo.setUserId(user.getId());
        userManagementPojo.setUserName(user.getUserName());
        return userManagementPojo;
    }

    private UserManagementPojo packageUserManagementPojo(UserManagementRedisPojo userManagementRedisPojo) {//封装对象 返回前端
        UserManagementPojo userManagementPojo = new UserManagementPojo();
        userManagementPojo.setUserId(userManagementRedisPojo.getUserId());
        userManagementPojo.setUserName(userManagementRedisPojo.getUserName());
        return userManagementPojo;
    }

    private UserManagementRedisPojo packageUser(User user) {//封装对象 存入redis
        UserManagementRedisPojo userManagementRedisPojo = new UserManagementRedisPojo();
        userManagementRedisPojo.setUserId(user.getId());
        userManagementRedisPojo.setUserName(user.getUserName());
        return userManagementRedisPojo;
    }

    private UserManagementRedisPojo packageUser(UserManagement userManagement) {//封装对象 存入redis
        //通过userId获取对应的用户信息
        User user = serviceHelper.getUserMapper().selectById(userManagement.getUserId());
        UserManagementRedisPojo userManagementRedisPojo = new UserManagementRedisPojo();
        userManagementRedisPojo.setUserId(user.getId());
        userManagementRedisPojo.setUserName(user.getUserName());
        return userManagementRedisPojo;
    }

    private List<String> deleteRedisUserManagement(User user, Integer departmentId) {//获取当前主账号id与所有的子账号id拼接部门id当做key去redis中删除相关数据
        List<String> list = new ArrayList<>();//用于存放主账号与子账号id并拼接部门id
        if (user.getFatherId() == null) {//判断当前用户是主
            QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
            userQueryWrapper.eq("father_id", user.getId());//需要查询主账号下的所有子账号id
            List<User> users = serviceHelper.getUserMapper().selectList(userQueryWrapper);//所有子账号id
            for (User user1 : users) {
                String id = RedisKeyPrefixEnum.USER_MANAGEMENT_DATA.getCode() + "_" + user1.getId() + "_" + departmentId;//子账号拼redis对应前缀
                list.add(id);//子账号id存入
            }
            list.add(RedisKeyPrefixEnum.USER_MANAGEMENT_DATA.getCode() + "_" + user.getId() + "_" + departmentId);//主账号拼redis对应前缀
        } else {//判断当前用户是子
            User userMain = serviceHelper.getUserMapper().selectById(user.getFatherId());//获取主账号
            QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
            userQueryWrapper.eq("father_id", userMain.getId());//获取主账号下的所有子账号
            List<User> users = serviceHelper.getUserMapper().selectList(userQueryWrapper);//所有子账号id
            for (User user1 : users) {
                String id = RedisKeyPrefixEnum.USER_MANAGEMENT_DATA.getCode() + "_" + user1.getId() + "_" + departmentId;//子账号拼redis对应前缀
                list.add(id);//子账号id存入
            }
            list.add(RedisKeyPrefixEnum.USER_MANAGEMENT_DATA.getCode() + "_" + userMain.getId() + "_" + departmentId);//主账号拼redis对应前缀
        }
        return list;
    }
}
